#include <iostream>
using std::cout;
using std::endl;

template <typename T>
class ObjectPool
{
public:
    T *New()
    {
        T *obj = nullptr;
        //优先使用换回来的内存对象，再次重复利用
        if (_freeList)
        {
            obj = (T*)_freeList;                 
            _freeList = *((void**)_freeList); // 得到next指针的地址
            
        }
        else
        {
            // 判断内存剩余数，不够一个对象大小重新开辟
            if (_remainBytes < sizeof(T))
            {
                _remainBytes=128 * 1024;
                _memory = (char *)malloc(128 * 1024);
                if (_memory == nullptr)
                    throw std::bad_alloc();
            }
            obj = (T*)_memory;
            //必须保证给出的内存大小至少能存储一个指针，也就是4个字节大小
            size_t objsize=sizeof(T)>sizeof(void*)?sizeof(T):sizeof(void*);
            _memory += objsize;
            _remainBytes -= objsize;
           
        }

        new(obj)T;
        return obj;
    }

    void Delete(T *obj)
    {
       
           obj->~T();    
		  //将释放的对象头插到自由链表
            
            //*((int*)obj)=nullptr;//利用32位平台指针四字节特性和整形指针解引用为四个字节达到使用内存块本身存储指针的目的，适用于32位平台
           // 与上同理，只不过上面的编译会报错将指针赋值给整形，但可以适用于32和64位平台//目的是为了让内存块本身拿出适合平台指针大小的空间去存储地址
            *(void **)obj = _freeList;
            _freeList = obj;
            
    }

private:
    char *_memory = nullptr; // 指向总内存的指针
    size_t _remainBytes = 0; // 总内存剩余内存数，用于判断是否需要开辟内存块
    void*_freeList = nullptr;  // 不用的内存块xx
};